/* 
 * File:   ExperimentDirectorThread.h
 * Author: jcrada
 *
 * Created on April 19, 2009, 7:46 PM
 */

#ifndef _EXPERIMENTDIRECTORTHREAD_H
#define	_EXPERIMENTDIRECTORTHREAD_H

#include "SimulationThread.h"
#include "ExperimentThread.h"
#include "Experiment.h"

#include <vector>
#include <QtCore/QString>
#include <QtCore/QReadWriteLock>
namespace jcrada {

    class ExperimentDirectorThread : public SimulationThread {

        Q_OBJECT

    public slots:
        void experimentMessage(const QString& msg) {
            emit message(msg);
        }

    private:
        std::vector<ExperimentThread*>* _experiments;
        int _next_experiment;
        QReadWriteLock* _lock;

    protected:
        virtual void saveToFile(const Experiment&);
        virtual std::string nextFileAvailable(const std::string& basename,
                const std::string& middlename, const std::string& extension);
    public:
        ExperimentDirectorThread(std::vector<ExperimentThread*>& experiments,
                BulletSimulator& simulator = BulletSimulator::getSingleton());
        virtual ~ExperimentDirectorThread();

        virtual void iterate();


        virtual QReadWriteLock& getLock() const {
            return *this->_lock;
        }

        virtual void setNextExperiment(int experiment){
            this->_next_experiment = experiment;
        }

        virtual ExperimentThread* getCurrentExperiment() const {
            ExperimentThread* result = NULL;
            getLock().lockForRead();
            if (_next_experiment < _experiments->size()) {
                result = _experiments->at(_next_experiment);
            }
            getLock().unlock();
            return result;
        }

        virtual void setSimulationSpeed(int speed) {
            SimulationThread::setSimulationSpeed(speed);
            ExperimentThread* experiment = getCurrentExperiment();
            if (experiment) {
                experiment->setSimulationSpeed(speed);
            }
            getLock().unlock();
        }

        virtual void stop() {
            int speed = getSimulationSpeed();
            setSimulationSpeed(0);
            setStopped(true);
            ExperimentThread* experiment = getCurrentExperiment();
            if (experiment){
                experiment->stop();
            }
            setSimulationSpeed(speed);
        }

    };
}


#endif	/* _EXPERIMENTDIRECTORTHREAD_H */

